#include "MatrixTransformationShader.h"
#include <glad/glad.h>
#include <glm/ext.hpp>
#include <glm/glm.hpp>
#include <iostream>
#include "GLFW/glfw3.h"
#include "glm/ext/matrix_transform.hpp"
#include "glm/ext/vector_float3.hpp"
#include "glm/trigonometric.hpp"
using namespace glm;

MatrixTransformationShader::MatrixTransformationShader()
{
    vertexShaderSource = "#version 330 core \n \
       layout(location=0) in vec3 aPos; \n\
       uniform mat4 transform;  \n\
       void main(){     \n\
            gl_Position = transform * vec4(aPos,1.0);\n\
       }\0";

    fragmentShaderSource = "#version 330 core \n\
        out vec4 FragColor;    \n\
        void main(){        \n\
            FragColor = vec4(0,0,0.7,1.0);            \n\
        }\0";
}

unsigned int MatrixTransformationShader::createShaderProgram()
{
    auto shaderProgram = ShaderProgram::createShaderProgram();

    transformMatrixId = glGetUniformLocation(shaderProgram, "transform");

    if (transformMatrixId == -1)
    {
        std::cout << "failed to get uniform mat4 transform" << std::endl;
    }
    return shaderProgram;
}
/*
具体 图元的变换顺序与 代码的变换顺序是相反的
代码中是先旋转后放大
但是实际效果是先旋转再放大
Remember that the actual transformation order should be read in reverse: even
though in code we first translate and then later rotate, the actual
transformations first apply a rotation and then a translation.
*/
void MatrixTransformationShader::update()
{
    // 设置旋转速度：每秒旋转10度
    static int rotation_speed = 10;
    float time = glfwGetTime();

    // 当前的旋转角度
    float rotation_degree = rotation_speed * time;

    // 声明对角线值为1的单位矩阵（单位矩阵除了对角线的值以外，其他元素都为0）
    mat4 transform(1.0f);

    // 单位矩阵乘以一个绕z轴旋转60度的旋转矩阵
    // 要旋转的轴（这里是z轴，即vec3(0,0,1)）必须是一个单位向量
    mat4 rotated = rotate(transform, radians(rotation_degree), vec3(0, 0, 1));

    // 把上述矩阵 的 x,y,z 轴都放大0.5倍
    mat4 scaled = scale(rotated, vec3(0.5, 0.5, 0.5));

    glUniformMatrix4fv(
        transformMatrixId,
        1, // 要发送几个矩阵
        /*
         是否需要对矩阵进行转置，OpenGL主要使用column-major ordering 布局的矩阵
         但是 GLM 计算库用的也是这个布局
         所以就不需要进行转置了
        */
        GL_FALSE,
        value_ptr(scaled) // GLM 的矩阵与OpenGL不兼容，所以要进行转换
    );
}